<?php

/**
 # com_jvframwork - JV Framework
 # @version		1.5.x
 # ------------------------------------------------------------------------
 # author    Open Source Code Solutions Co
 # copyright Copyright (C) 2011 joomlavi.com. All Rights Reserved.
 # @license - http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL or later.
 # Websites: http://www.joomlavi.com
 # Technical Support:  http://www.joomlavi.com/my-tickets.html
-------------------------------------------------------------------------*/
// no direct access
defined('_JEXEC') or die('Restricted access');

jimport('joomla.application.component.model');
jimport('joomla.application.component.helper');
jimport('joomla.filesystem.file');
jimport('joomla.filesystem.folder');
jimport('joomla.filesystem.archive');
jimport('joomla.filesystem.path');
jimport('joomla.installer.helper');

/**
 * Default Model
 *
 * @package   Joomla
 * @subpackage  Updater
 * @since   1.5
 */
class JVframeworkModelUpdate extends JVModel {

    public $_filter_order = 'filter_order_fd';
    public $_filter_order_Dir = 'filter_order_Dir_fd';
    public $_key = 'id';
    public $_updateInfo = null;
    
    /**
     * Construct method
     * 
     * @return void
     */
    function __construct() {
        parent::__construct();        
    }

    function _buildQuery() {
    }
    
    function send(){        
        $data = JRequest::get('post'); 
        $name  = 'Framework Client Feedback';
        $body  = "Type: {$data['type']}\n";    
        $body .= "Relation: {$data['relation']}\n";
        $body .= "Message:\n".$data['message']."\n"; 
           
        JUtility::sendMail($data['email'], $name, 'info@joomlavi.com', $data['subject'], $body);
        return true;
    }
    
    function check(){
        $canUpdate = $status = 0;
        
        $updateinfo = $this->getUpdateInfo();   
        $fwUpdate  = isset($updateinfo['com_jvframework16']) ? $updateinfo['com_jvframework16']: array(); 
               
        $version = $this->getCurrentVersion();
        $upversion = isset($fwUpdate['version']) ? $fwUpdate['version']: -1;  
        
        if($version == -1 || $upversion == -1) return false;
                
        $canUpdates = explode(',', $fwUpdate['canupdate']);
        
        if(version_compare($version, $upversion)){
            $status = 1;
            if(in_array($version, $canUpdates)){
                $canUpdate = 1;
                
            } else{
                $status = 0;
                JError::raiseWarning('200', 'New version of JV Framework found, but can\'t update for this version. Please go to <a target="_blank" href="http://joomlavi.com" >Joomlavi.com</a> to download new version !');
            
            }
        }   
        
        $fwUpdate['canUpdate'] = $canUpdate;       
        $fwUpdate['status'] = $status;
        
        return json_encode($fwUpdate);
    }
    
    function getCurrentVersion(){
        $info = array(); $cfgPath = JPATH_COMPONENT.DS.'jvframework.xml';            
        if(JFile::exists($cfgPath)) $info =& JApplicationHelper::parseXMLInstallFile($cfgPath);
        $version   = isset($info['version']) ? $info['version']: -1;
        
        return $version;
    }
    
    /**
     *  Get Update Info
     * 
     * @param mixed $ext
     * @return array info
     */
    function getUpdateInfo() {
        if($this->_updateInfo == null){
            $content = fopen('http://joomlavi.com/update/update.xml', 'r');
            $content = fread($content, 1000); 
            $xmlString = $content;
            $xmlObj = $this->getXmlParser($xmlString);
            $data = $this->xml2Array($xmlObj);
            
            $info = array();        
            foreach($data['ext'] as $exts){           
                $info[$exts['name']] = $exts;
            }
            
            $this->_updateInfo = $info;
        }
        
        return $this->_updateInfo;
    }
    
    /**
     * Get xml parser
     * 
     * @param mixed $xmlString
     * @return object xml
     */
    function getXmlParser($xmlString) {
        $xmlobj = &JFactory::getXMLParser('Simple');
        $xmlobj->loadString($xmlString);
        $xmlobj = &$xmlobj->document;

        return $xmlobj;
    }

    /**
     * Get Ext Update Info
     * 
     * @param string $ext
     * @return
     */
    function getExtUpdateInfo($ext) {
       if($this->_updateInfo[$ext]){
            return $this->_updateInfo[$ext];
       }
        return;
    }

    /**
     * Xml to array
     * 
     * @param object $xmlObj
     * @return array
     */
    function xml2Array($xmlObj) {
        $array = array();
        
        if(trim($xmlObj->data()) != '')
        $array[$xmlObj->name()] = $xmlObj->data();

        if (count($xmlObj->children())) {
            foreach ($xmlObj->children() as $child) {
                $data = $this->xml2Array($child);
                if (is_array($data) && $child->name() != 'ext') {
                    $array += $data;
                } else {
                    $array[$child->name()][] = $data;
                }

            }
        }

        return $array;
    }
    
    function updateBasetheme(){
        $target = JPATH_ROOT.DS.'tmp'.DS.'basethemes.zip';                
        $p_file = $this->downloadPackage('http://joomlavi.com/update/basethemes.zip',$target);
                
        if (!$p_file) {
			die(JText::_('Invalid URL'));
			return false;
		} else{
		    if($this->unpack($p_file, JVPATH_TEMPLATE.'jv-framework')) JFile::delete($p_file);
		} 
                
        return true;        
    }
    
    function doUpdate() {         
        $name   = JRequest::getVar('name', '', 'post');
        $url    = JRequest::getVar('url', '', 'post');
        $path   = JPATH_COMPONENT.DS;
        $version= JRequest::getVar('version', '', 'post'); 
        $current= JRequest::getVar('current', '', 'post');              
        $ver    = (int) str_replace('.','',$version);        
        $target = JPATH_ROOT.DS.'tmp'.DS.$name;                
        $p_file = $this->downloadPackage($url.$name,$target);
        $dirname= $this->explodeName($name)->name;
        
        if (!$p_file) {
			die(JText::_('Invalid URL'));
			return false;
		} else{
		    if($this->unpack($p_file,JPATH_ROOT)){
		       JFile::delete($p_file);
		    } 
		}        
        
        if(JFolder::exists($path)){
            //if(!$this->backup($name, $path, 'zip',$current, $version)) return false;
        }            
        return true;           
        
    }
    
    function backup($name, $path, $ext,$current, $version) { 
        $folder = @explode('.',$name);  
        $tmp    = JPATH_ROOT.DS.'tmp'.DS.$folder[0].DS;
        $backup_ext_path= JPATH_ROOT.DS.'jvframework_backup'.DS;
        $backup_path    = $backup_ext_path.$current;
        $backup_dfsource_path = $backup_ext_path.$current.'_to_'.$version;    
        $addFiles       = array();
        $compare        = array();
        $editedFile     = array();
        
        if(JFolder::exists($backup_dfsource_path)){
            JFolder::delete($backup_dfsource_path);
        }
                
        if(!JFolder::create($backup_ext_path)) return false;
        if(!JFolder::create($backup_dfsource_path)) return false;
        if(!JFolder::copy($path,$backup_path,'',true)) return false;
        $fileOlds = $this->parseDirectory($path);
        $fileNews = $this->parseDirectory($tmp);
                
        for ($i=0;$i<count($fileNews);$i++){
			$filenew = trim($fileNews[$i]);
            $new = str_replace(array('/','\\\\'),array(DS,DS),$filenew); 
            $old = str_replace($tmp,$path,$new);            
            $fod = substr($filenew,0,(strrpos($filenew,'/')+1));            
            $fod = str_replace(array('/','\\\\'),array(DS,DS),$fod);
            $fod = str_replace($tmp,'',$fod);
                        
            if(JFile::exists($old)){
                if(JFile::read($new) != JFile::read($old)){                    
                    $editedFile['old'][]    = $old;
                    $editedFile['folder'][] = $fod;
                    $editedFile['new'][]    = $new;
                }
            } else {
                $addFiles[] = $new;
            }
		}
        
        if(count($editedFile)){
            foreach($editedFile['old'] as $key => $old){
                $bk_folder = $backup_dfsource_path.DS.$editedFile['folder'][$key];
                if(!JFolder::exists($bk_folder)){
                    JFolder::create($bk_folder);
                }
                JFile::copy($old,str_replace($path,$backup_dfsource_path.DS,$old));
            }
            
            foreach($editedFile['new'] as $key => $new){
                $dest = $path.$editedFile['folder'][$key];
                if(!JFolder::exists($dest)){
                    JFolder::create($dest);
                }
                JFile::copy($new,str_replace($tmp,$path,$new));
            }
        }
        if(!JFolder::delete($tmp)) return false;
        
        return true;
         
    }
    
    /**
	  * Function to parse a directory to return all its files and sub directories as array
	  *
	  * @param string $dir
	  * @access protected 
	  * @return array
	  */
	protected function parseDirectory($rootPath, $seperator="/"){
		$fileArray=array();
		$handle = opendir($rootPath);
		while( ($file = @readdir($handle))!==false) {
			if($file !='.' && $file !='..'){
				if (is_dir($rootPath.$seperator.$file)){
					$array=$this->parseDirectory($rootPath.$seperator.$file);
					$fileArray=array_merge($array,$fileArray);
				}
				else {
					$fileArray[]=$rootPath.$seperator.$file;
				}
			}
		}		
		return $fileArray;
	}
    

    function downloadPackage($url, $target = false) {
        $config = &JFactory::getConfig();

        // Capture PHP errors
        $php_errormsg = 'Error Unknown';
        ini_set('track_errors', true);

        // Set user agent
        ini_set('user_agent', "Joomla! 1.5 Installer");

        // Open the remote server socket for reading
        $inputHandle = @fopen($url, "r");
        $error = strstr($php_errormsg, 'failed to open stream:');
        if (!$inputHandle) {
            JError::raiseWarning(42, JText::_('SERVER_CONNECT_FAILED') . ', ' . $error);
            return false;
        }

        // Initialize contents buffer
        $contents = null;
        
        // Set the target path if not given
		if (!$target) {
			$target = JPATH_ROOT.DS.'tmp'.DS.JInstallerHelper::getFilenameFromURL($url);
		} else {
			$target = JPATH_ROOT.DS.'tmp'.DS.basename($target);
		}
        while (!feof($inputHandle)) {
            $contents .= fread($inputHandle, 4096);
            if ($contents == false) {
                JError::raiseWarning(44, 'Failed reading network resource: ' . $php_errormsg);
                return false;
            }
        }

        // Write buffer to file
        JFile::write($target, $contents);

        // Close file pointer resource
        fclose($inputHandle);

        // Return the name of the downloaded package
        return $target;
    }
    
   
    function unpack($p_filename, $updatePath) { 
        // Path to the archive
        $archivename = $p_filename;


        // Temporary folder to extract the archive into
        $tmpdir = '';

        // Clean the paths to use for archive extraction
        $extractdir = JPath::clean($updatePath);
        $archivename = JPath::clean($archivename); 
        // do the unpacking of the archive
        $result = JArchive::extract($archivename, $extractdir);

        if ($result === false) {
            return false;
        }


        /*
        * Lets set the extraction directory and package file in the result array so we can
        * cleanup everything properly later on.
        */
        $retval['extractdir'] = $extractdir;
        $retval['packagefile'] = $archivename;

        /*
        * Try to find the correct install directory.  In case the package is inside a
        * subdirectory detect this and set the install directory to the correct path.
        *
        * List all the items in the installation directory.  If there is only one, and
        * it is a folder, then we will set that folder to be the installation folder.
        */
        $dirList = array_merge(JFolder::files($extractdir, ''), JFolder::folders($extractdir,
            ''));

        if (count($dirList) == 1) {
            if (JFolder::exists($extractdir . DS . $dirList[0])) {
                $extractdir = JPath::clean($extractdir . DS . $dirList[0]);
            }
        }

        /*
        * We have found the install directory so lets set it and then move on
        * to detecting the extension type.
        */
        $retval['dir'] = $extractdir;

        /*
        * Get the extension type and return the directory/type array on success or
        * false on fail.
        */

        return $retval;

    }
    
    public function explodeName($name){
        $names       = new stdClass;        
        $dot         = strrpos($name, '.');
		$names->name = strtolower(substr($name, 0, $dot));
		$names->ext  = strtolower(substr($name, $dot+1));
        
        return $names;
    }
    
}
